﻿using System;
using System.Collections.Generic;
using XEvolve.Core.Runtime.Attributes;
using XEvolve.Core.Runtime;
using System.Windows;
using XEvolve.Presentation.Input;

namespace XEvolve.Presentation.Internal
{
    internal class ViewManager : INavigator
    {
        private const string SINGLETON_VIEW = "SINGLETON_VIEW";
        private readonly IExtensionPoint views;
        private readonly IDictionary<ViewKey, WindowAdapter> viewInstances = new Dictionary<ViewKey, WindowAdapter>();

        public ViewManager([ExtensionPoint("xevolve.views")]IExtensionPoint views) 
        {
            this.views = views;
        }

        public void Open(object viewId)
        {
            Open(viewId, null);
        }

        public void Open(object viewId, object parameter)
        {
            Open(viewId, SINGLETON_VIEW, parameter);
        }

        public void Close(object viewId)
        {
            Close(viewId, SINGLETON_VIEW);
        }

        public void Open(object viewId, object id, object parameter)
        {
            var key = new ViewKey { ViewType = viewId, ViewId = id };
            if (viewInstances.ContainsKey(key))
            {
                viewInstances[key].BringToFront();
                return;
            }
            var view = (Window)views.GetExtension(viewId);
            var context = CommandBindings.GetContext(view);
            if (!context.Contains("XEvolve.Window"))
            {
                CommandBindings.SetContext(view, context + ",XEvolve.Window");
            }
            var viewAdapter = new WindowAdapter(key, view, this);
            viewInstances[key] = viewAdapter;
            viewAdapter.Show(parameter);
        }

        public void Close(object viewId, object id)
        {
            var key = new ViewKey { ViewType = viewId, ViewId = id };
            if (viewInstances.ContainsKey(key))
            {
                viewInstances[key].Close();
            }
        }

        internal void CloseView(ViewKey viewKey)
        {
            viewInstances.Remove(viewKey);
        }
    }

    class ViewKey
    {
        public object ViewType { get; set; }
        public object ViewId { get; set; }

        public bool Equals(ViewKey obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            return Equals(obj.ViewType, ViewType) && Equals(obj.ViewId, ViewId);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (ViewKey)) return false;
            return Equals((ViewKey) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return ((ViewType != null ? ViewType.GetHashCode() : 0)*397) ^ (ViewId != null ? ViewId.GetHashCode() : 0);
            }
        }
    }
}